/**
 * @class   wosh::Bundle
 * @brief   Base interface for WOSH Bundles. Bundles are services, drivers
 *          and even (virtual) devices. They interact and exchange information
 *          through wosh::Bus.
 *          Implementations are located in /src/bundles folder, classified
 *          as Device or Service.
 *
 *          wosh::BundleManager manages (de)allocation, life cycle of each
 *          bundle.
 *
 * @see     wosh::BundleGeneric
 * @see     \ref page_bundles
 ****************************************************************************
 * @version 0.8.013 $Id: Bundle.h 2544 2010-05-26 02:35:43Z alex $
 * @author  Alessandro Polo
 ****************************************************************************/
/* Copyright (c) 2007-2010, WOSH - Wide Open Smart Home 
 * by Alessandro Polo - OpenSmartHome.com
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the OpenSmartHome.com WOSH nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY Alessandro Polo ''AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL Alessandro Polo BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ****************************************************************************/

#ifndef __WOSH_Core_Bundle_H__
 #define __WOSH_Core_Bundle_H__

 #include <woshDefs.h>
 #include <core/Object.h>
 #include <core/Bus.h>

 #include <interfaces/IBundle.h>


namespace wosh {

 #define _Bundle_KEY_State				"BundleState"

 #define _Bundle_METHOD_Start			"bundle_start"
 #define _Bundle_METHOD_Stop			"bundle_stop"
 #define _Bundle_METHOD_Restart			"bundle_restart"

 #define _Bundle_METHOD_Diagnostic		"bundle_diag"


#define WOSH_BUNDLE(CLASSNAME)			\
		WOSH_CLASSNAME(CLASSNAME)		\
		WOSH_CLASS_ABSTRACT(false)


class IBundleHandler;
class BundleManager;
class MethodsProvider;
class BundleRequirements;
class InterfacesProvider;
class PropertiesProvider;
class SecurityTokenProvider;

class Bundle :		public Object,
					public virtual wosh::interfaces::IBundle,
					public virtual IBusListener
 {
	WOSH_CLASSNAME(wosh::Bundle)
	WOSH_CLASS_ABSTRACT(true)

	public:
		///@brief States of a generic Bundle
		enum BUNDLE_STATE {
			STATE_UNKNOWN		= 0x00,
			STATE_CREATING		= 0x01,
			STATE_CREATED		= 0x02,
			STATE_STARTING		= 0x04,
			STATE_STARTED		= 0x08,
			STATE_STOPPING		= 0x10, // 16
			STATE_STOPPED		= 0x20, // 32
			STATE_DESTROYING	= 0x40, // 64
			STATE_DESTROYED		= 0x80, // 128
			STATE_FAILURE		= 0xFF  // 255
		};

	protected:
		/**
		 * @brief  Empty constructor.
		 * @param parent [in] the parent object, usually NULL, still not really used.
		 */
		Bundle( wosh::Object* parent = NULL )
			: Object(parent) {
			setBundleState(Bundle::STATE_CREATING, false);
		 }
	public:
		/**
		 * @brief  Empty destructor.
		 */
		virtual ~Bundle() {
			setBundleState(Bundle::STATE_DESTROYED, true);
		 }


/** @name Bundle interface - management
 * @{
 ******************************************************************************/
	public:

		// called by BundleManager
		virtual WRESULT bundleStart() = 0;
		virtual WRESULT bundleRestart() = 0;
		virtual WRESULT bundleStop() = 0;

		virtual WRESULT bundleDiagnostic() = 0;
		virtual WRESULT bundleSnapshotState( long id ) = 0;

	public:
		virtual const InterfacesProvider* bundleInterfaces() const = 0;
		virtual const BundleRequirements* bundleRequirements() const = 0;
		virtual const MethodsProvider* bundleMethods() const = 0;
		virtual const PropertiesProvider* bundleProperties() const = 0;
		virtual PropertiesProvider* bundleProperties() = 0;
		virtual const SecurityTokenProvider* bundleCredentials() const = 0;

//@}
/** @name Getters
 * @{
 ******************************************************************************/
	public:
		inline Bundle::BUNDLE_STATE getBundleState() const	{ return this->bundleState; }

		inline const char* getBundleStateAsString() const	{ return getBundleStateAsString(this->bundleState); }

		inline bool isBundleRunning() const 				{ return (this->bundleState == Bundle::STATE_STARTED); }

		static const char* getBundleStateAsString( Bundle::BUNDLE_STATE state ) {
			switch(state) {
				case STATE_CREATING:	return "CREATING";
				case STATE_CREATED:		return "CREATED";
				case STATE_STARTING:	return "STARTING";
				case STATE_STARTED:		return "STARTED";
				case STATE_STOPPING:	return "STOPPING";
				case STATE_STOPPED:		return "STOPPED";
				case STATE_DESTROYING:	return "DESTROYING";
				case STATE_DESTROYED:	return "DESTROYED";
				case STATE_FAILURE:		return "FAILURE";
				default:				return "UNKNOWN";
			 }
		 }

//@}
	protected:
		// event from this Bundle, raised for BundleManager
		virtual void setBundleState( Bundle::BUNDLE_STATE state, bool raise_event = true ) {
			this->bundleState = state;
			if ( !raise_event ) return;
		 }

		friend class wosh::BundleManager;
//@}
/** @name Internal vars
 * @{
 ******************************************************************************/
	private:
		Bundle::BUNDLE_STATE bundleState;	// current state of the bundle
//@}
	private:
		Bundle(const Bundle&) : Object() { }
		Bundle& operator=(const Bundle&) { return *this; }


}; // class def


}; // namespace wosh

#endif //__WOSH_Core_Bundle_H__
